package com.sdyeda.iotapi;

import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.alibaba.fastjson.JSONObject;
import com.sdyeda.tools.HexTools;

public class IotYanyi implements IotBase {

	private static final int sendbuffsize = 21;
	private byte[] sendbuff = new byte[sendbuffsize];
	private byte[] databuff;
	// 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20
	// 头（2）动作 数据长度 保留 |传感器编号，8字节 |操作时间6字节 |校验和
	// AA 75 10 高字在前 00 | | |

	public IotYanyi() {
		clearBuffer();
	}

	@Override
	public byte[] MakeSendBuff(String id) {
		return MakeSendBuff(id, "read");
	}

	@Override
	public byte[] MakeSendBuff(String id, String command) {

		if (!isValidCommand(command)) {
			return null;
		}

		// 头55AA，长度第4字节固定值0x0E=14
		// setHead();
		sendbuff[0] = (byte) 0xAA;
		sendbuff[1] = (byte) 0x75;
		sendbuff[2] = (command == "reset") ? (byte) 0x80 : (byte) 0x10;
		sendbuff[4] = (byte) 0x0E; // 数据长度，14字节
		// id 从第6字节开始，长度8字节
		System.arraycopy(HexTools.hexStringToByteArray(id), 0, sendbuff, 6, 8);
		// time 从第14字节开始，长度6字节 例如2023年1约2日=20230102
		System.arraycopy(HexTools.getBytesTimeBCD(), 0, sendbuff, 14, 6); // 年月日
		setCRC();
		return sendbuff;
	}

	@Override
	public String DecodeToJson(byte[] receive) {
		return JSONObject.toJSONString(DecodeToMap(receive));
	}

	// 通用传感器
	// 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F|
	// 传感器编号8字节 |BCD时间6字节 |温度*0.1|
	// 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F|
	// 测量值-偏移值-应变频-补偿频-|单位 4字节|类型|自编号16字节
	// 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F|
	// --------------------------------------|型号8字节
	// 30 31 32 33 34|总计53字节
	@Override
	public Map<String, Object> DecodeToMap(byte[] receive) {
		getData(receive);
		if (databuff == null)
			return null;

		Map<String, Object> result = new HashMap<String, Object>();
		// id 0-8字节
		result.put("id", (databuff.length >= 8) ? HexTools.bytesToHexString(databuff, 0, 8) : null);
		// 时间
		result.put("time", getTime(8));
		result.put("temp", (databuff.length >= 16) ? deCodeInt(14) * 0.1 : null); // 温度
		result.put("value", (databuff.length >= 18) ? deCodeInt(16) : null); // 测量值--原值
		result.put("offset", (databuff.length >= 20) ? deCodeInt(18) : null); // 偏移值--原值
		result.put("strain", (databuff.length >= 22) ? deCodeInt(20) * 0.1 : null); // 应变频率
		result.put("compen", (databuff.length >= 24) ? deCodeInt(22) * 0.1 : null); // 补偿频率

		result.put("unit", (databuff.length >= 28) ? toGB2312(24, 4) : null); // 单位
		result.put("strid", (databuff.length >= 45) ? toGB2312(29, 16) : null); // 自编号-字符串？
		result.put("strtype", (databuff.length >= 53) ? toGB2312(45, 8) : null); // 设备类型-字符串

		return result;
	}

	@Override
	public List<String> Skill() {
		List<String> result = new ArrayList<String>();
		result.add("read");
		result.add("reset");
		return result;
	}

	public String toString(byte[] buff) {
		if (buff != null) {
			return HexTools.bytesToHex(buff);
		} else {
			return "";
		}
	}

	// 内部函数
	// 是否支持该命令
	private boolean isValidCommand(String command) {
		boolean result = false;
		List<String> skill = Skill();
		for (int i = 0; i < skill.size(); i++) {
			if (skill.get(i).equals(command)) {
				result = true;
			}
		}
		;
		return result;
	}

	// 清除sendbuff
	private void clearBuffer() {
		for (int i = 0; i < sendbuff.length; i++)
			sendbuff[i] = 0;
	}

	// 设置sendbuff校验位
	private void setCRC() {
		byte check = 0;
		for (int i = 0; i < sendbuff.length - 1; i++) {
			check ^= sendbuff[i];
		}
		sendbuff[sendbuff.length - 1] = check;
	}

	// --------------|
	// 以下是分析接收buff函数

	// 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F|
	// AA 75 命令 长 度 00 data----一般53字节
	// 10 1F|
	// ----
	// 20 3F|
	// ---- SUM
	// 30 31 32 33 34 35 36 37 38 39 40 4A|总计60字节
	private void getData(byte[] receive) {
		int seek = findHead(receive);
		if (seek <= 0) {
			databuff = null;
			return;
		}

		// 数据长度
		byte[] dlbuff = new byte[2];
		System.arraycopy(receive, seek + 3, dlbuff, 0, 2);
		// System.out.println(HexTools.byte2ToInt(datalength));
		int datalength = HexTools.byte2ToInt(dlbuff);

		// 数据包（包含7字节头）
		byte[] datapack = new byte[datalength + 7];
		databuff = new byte[datalength];
		if (receive.length >= datalength + 7) {
			System.arraycopy(receive, seek, datapack, 0, receive.length - seek);
			if (checkCRC(datapack)) {
				// 去掉7字节头
				System.arraycopy(datapack, 6, databuff, 0, datalength);
			} else {
				databuff = null;
				return;
			}
		} else {
			databuff = null;
			return;
		}

	}

	int findHead(byte[] buff) {
		byte[] head = { (byte) 0x55, 0x7A };
		byte[] temp = new byte[2];
		for (int i = 0; i < buff.length - 2; i++) {
			System.arraycopy(buff, i, temp, 0, 2);
			if (Arrays.equals(temp, head)) {
				return i;
			}
		}
		return -1; // 在剩下60字节也未发现
	}

	boolean checkCRC(byte[] buff) {

		int size = buff.length;
		byte check = buff[0];
		for (int i = 1; i < size - 1; i++) {
			check ^= buff[i];
		}
		// System.out.println(check == buf[size - 1]);
		return (check == buff[size - 1]);
	}

	// 从第32字节开始，总计8字节
	private Date getTime(int from) {
		if (databuff.length >= from + 6) {
			byte[] bcdtime = new byte[6];
			System.arraycopy(databuff, from, bcdtime, 0, 6);
			return HexTools.BytesBCDtoDate(bcdtime);
		} else {
			return new Date();
		}
	}

	// 两字节int值
	int deCodeInt(int pos) {
		byte[] by = new byte[2];
		by[0] = by[1] = (byte) 0x00;
		System.arraycopy(databuff, pos, by, 0, 2);
		return HexTools.byte2ToInt(by);
	}

	String toGB2312(int from, int len) {
		byte[] data = new byte[len];
		System.arraycopy(sendbuff, 24, data, 0, len);
		try {
			return new String(data, "GB2312").trim();
		} catch (UnsupportedEncodingException e) {
			return null;
		}
	}

}
